<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="zui/zui.css">
    <style>
        .menu {
            box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
            border-radius: 4px;
            position: absolute;
            display: none;
        }

        #list {
            margin: 160px;
            padding: 20px;
            display: flex;
            gap: 26px;
            border: 1px solid lightgray;
            justify-content: flex-start;
            position: relative;
            height: 1000px;
        }
    </style>
</head>

<body style="background-color: antiquewhite;margin: 24px;">
    <div id="list">
        <button class="btn outline m">按钮1</button>
        <button class="btn outline m">按钮2</button>
        <button class="btn outline m">按钮3</button>
    </div>
    <menu class="menu w-32">
        <li class="menu-item"><a>删除</a></li>
    </menu>
</body>
<script>
    /*
     * class版本
     */
    class AutoCloseHelper {
        constructor(element) {
            this.element = element;
            // 注意这里要用箭头函数，不然this会变成生产事件的元素
            // 如果要使普通函数里的this不改变，要用closeHandler.bind(this)包装下
            this.closeHandler = event => {
                if (!this.element.contains(event.target)) {
                    element.style.display = 'none';
                    this.cancle();
                }
            }
        }

        setup() {
            document.addEventListener('click', this.closeHandler);
        }

        cancle() {
            document.removeEventListener('click', this.closeHandler);
        }
    }


    /**
     * 实现点击元素外部时自动隐藏元素
     * @param {Element} element 要设置自动隐藏的元素
     * @returns 
     */
    function autoCloseHelper(element) {
        function closeHandler(event) {
            if (!element.contains(event.target)) {
                element.style.display = 'none';
                removeCloseHandler()
            }
        }
        function addCloseHandler() {
            document.addEventListener('click', closeHandler);
        }
        function removeCloseHandler() {
            document.removeEventListener('click', closeHandler);
        }
        return {
            setup: addCloseHandler,
            cancle: removeCloseHandler
        };
    }

    /**
     * 获取元素距离body的上偏移和左偏移
     */
    const axOffset = (elem) => {
        let totalLeft,
            totalTop,
            scrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft,
            scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        totalLeft = elem.getBoundingClientRect().left + scrollLeft;
        totalTop = elem.getBoundingClientRect().top + scrollTop;
        return {
            left: totalLeft,
            top: totalTop
        }
    }

    const mores = document.querySelectorAll('.m');
    const del = document.querySelector('.menu-item');
    const menu = document.querySelector('.menu');
    mores.forEach(more => {
        more.addEventListener('click', moreClickHandle);
    })
    const closeHelper = autoCloseHelper(menu);
    function moreClickHandle(event) {
        event.stopPropagation();
        menu.style.display = 'block';
        //menu.style.top = `${event.pageY}px`;
        //menu.style.left = `${event.pageX}px`;
        let offset = axOffset(this);
        menu.style.top = `${offset.top + this.clientHeight + 6}px`;
        menu.style.left = `${offset.left}px`;
        closeHelper.setup();
        // del.onclick = (e) => {
        //     e.stopPropagation();
        //     closeHelper.cancleAutoClose();
        //     menu.style.display = 'none';
        //     this.remove();
        // };
        // 用bind可以不用像上面注释代码一样使用闭包来传递被点击的button对象
        del.onclick = delClickHandle.bind(null, this);
        //del.onclick = (e) => delClickHandle(this, e);
    }

    function delClickHandle(button, event) {
        event.stopPropagation();
        closeHelper.cancle();
        menu.style.display = 'none';
        button.remove();
    }
</script>

</html>